# 已知存在一个按非降序排列的整数数组 nums ，数组中的值不必互不相同。
#  在传递给函数之前，nums 在预先未知的某个下标 k（0 <= k < nums.length）上进行了 旋转 ，
#  使数组变为 [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]]（下标 从 0 开始 计数）。
#  例如， [0,1,2,4,4,4,5,6,6,7] 在下标 5 处经旋转后可能变为 [4,5,6,6,7,0,1,2,4,4] 。
#
#  给你 旋转后 的数组 nums 和一个整数 target ，请你编写一个函数来判断给定的目标值是否存在于数组中。如果 nums 中存在这个目标值
# target ，则返回 true ，否则返回 false 。
#
#  示例 1：
# 输入：nums = [2,5,6,0,0,1,2], target = 0
# 输出：true
#
#  示例 2：
# 输入：nums = [2,5,6,0,0,1,2], target = 3
# 输出：false
from typing import List


class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        """
         数组中有重复元素的情况，二分查找时可能会有 nums[left]=nums[mid]=nums[right]，
         此时无法判断区间 [left,mid] 和区间 [mid+1,right] 哪个是有序的。
         例如 nums=[3,1,2,3,3,3,3]，target=2，首次二分时无法判断区间 [0,3] 和区间 [4,6] 哪个是有序的。
         对于这种情况，此时只能将当前二分区间的左边界加一，右边界减一，然后在新区间上继续二分查找。
        :param nums:
        :param target:
        :return:
        """
        low, high = 0, len(nums) - 1
        while low <= high:
            mid = low + ((high - low) >> 1)
            if nums[mid] == target:
                return True
            if nums[low] == nums[mid] and nums[mid] == nums[high]:  # 此时无法判断区间 哪个部分是有序的情况
                low += 1
                high -= 1
            elif nums[low] <= nums[mid]:  # 左半部分有序
                if nums[low] <= target and target < nums[mid]:
                    high = mid - 1
                else:
                    low = mid + 1
            else:  # 右半部分有序
                if nums[mid] < target and target <= nums[high]:
                    low = mid + 1
                else:
                    high = mid - 1
        return False


if __name__ == "__main__":
    nums = [2, 5, 6, 0, 0, 1, 2]
    target = 0
    print(Solution().search(nums, target))
